package org.linlinjava.litemall.wx.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.LitemallGoodsProduct;
import org.linlinjava.litemall.db.domain.LitemallShop;
import org.linlinjava.litemall.db.domain.LumierePayMemberUserVo;
import org.linlinjava.litemall.db.dto.AdminShopSpecialDateDTO;
import org.linlinjava.litemall.db.service.LitemallGoodsProductService;
import org.linlinjava.litemall.db.service.LitemallShopService;
import org.linlinjava.litemall.db.util.LocalDateTimeUtils;
import org.linlinjava.litemall.db.util.PageTools;
import org.linlinjava.litemall.wx.util.LocationUtils;
import org.linlinjava.litemall.wx.util.PageUtil;
import org.linlinjava.litemall.wx.vo.WxShopVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ：stephen
 * @date ：Created in 2019/12/17 18:37
 * @description：TODO
 */

@Service
public class WxShopService {
    @Autowired
    private LitemallShopService litemallShopService;

    @Autowired
    private LitemallGoodsProductService litemallGoodsProductService;

    public Object all(BigDecimal longitude, BigDecimal latitude, Integer type,Integer page,Integer limit){
        //PageHelper.startPage(page, limit);
        List<LitemallShop> all = litemallShopService.all();

        if(null != longitude && null != latitude){
            List<WxShopVo> collect = all.stream().map(o->{
                WxShopVo shopVo = new WxShopVo();
                BeanUtils.copyProperties(o, shopVo);
                shopVo.setOpen(getOpenStatus(o));
                LocalTime[] businessHours = shopBusinessHours(o);
                shopVo.setOpenTime(String.valueOf(businessHours[0]));
                shopVo.setCloseTime(String.valueOf(businessHours[1]));
                shopVo.setDistance(LocationUtils.getDistance(latitude.doubleValue(), longitude.doubleValue(), o.getLatitude().doubleValue(), o.getLongitude().doubleValue()));
                return shopVo;
            }).sorted((o1, o2) -> {
                return o1.getDistance()
                        .compareTo(o2.getDistance());
            }).filter(c->{
                if(null == type){
                    return true;
                }
                if(Arrays.asList(c.getTypes()).indexOf(type) >= 0){
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            return ResponseUtil.ok(collect);
        }else{
            List<WxShopVo> collect = all.stream().map(o->{
                WxShopVo shopVo = new WxShopVo();
                BeanUtils.copyProperties(o, shopVo);
                shopVo.setOpen(getOpenStatus(o));
                LocalTime[] businessHours = shopBusinessHours(o);
                shopVo.setOpenTime(businessHours[0].toString());
                shopVo.setCloseTime(businessHours[1].toString());
                return shopVo;
            }).filter(c -> {
                if(null == type){
                    return true;
                }
                if (Arrays.asList(c.getTypes()).indexOf(type) >= 0) {
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            return ResponseUtil.ok(collect);
        }

    }

    public LocalTime[] shopBusinessHours(LitemallShop shop){
        List<LocalTime[]> weeksTime = shop.getWeeksTime();
        if (weeksTime == null) {
            return new LocalTime[]{LocalTime.parse("00:00"),LocalTime.parse("00:00")};
        }
        // 获取当前日期和时间
        LocalDate currentDate = LocalDate.now();

        // 获取当前是星期几
        DayOfWeek currentDayOfWeek = currentDate.getDayOfWeek();

        // 获取对应的门店营业时间
        LocalTime[] businessHours = weeksTime.get(currentDayOfWeek.getValue() - 1);
        List<AdminShopSpecialDateDTO> specialDateList = shop.getSpecial();
        if(specialDateList!=null){
            LocalDate today = LocalDate.now();
            // 遍历集合中的每个AdminShopSpecialDateDTO对象
            for (AdminShopSpecialDateDTO dto : specialDateList) {
                LocalDate specialDate = dto.getSpecialDate();
                LocalTime[] specialTime = dto.getSpecialTime();

                // 在这里进行特定逻辑处理，判断门店是否营业
                // 判断specialDate是否是今天
                if (!specialDate.isEqual(today)) {
                    continue;
                }
                // 判断当前时间是否在营业时间范围内
                businessHours=specialTime;
            }
        }
        return businessHours;
    }

    public Object queryGoodsShop(Integer goodsId,BigDecimal longitude, BigDecimal latitude, Integer type,Integer page,Integer limit){
        //PageHelper.startPage(page, limit);
        List<LitemallShop> shops = litemallShopService.all();
        if(CollUtil.isEmpty(shops)){
            List<WxShopVo> collect = CollUtil.newArrayList();
            return collect;
        }
        if(null != longitude && null != latitude){
            List<WxShopVo> collect = shops.stream().map(o->{
                WxShopVo shopVo = new WxShopVo();
                BeanUtils.copyProperties(o, shopVo);
                shopVo.setOpen(validShop(o.getId()));
                LocalTime[] businessHours = shopBusinessHours(o);
                shopVo.setOpenTime(String.valueOf(businessHours[0]));
                shopVo.setCloseTime(String.valueOf(businessHours[1]));
                shopVo.setDistance(LocationUtils.getDistance(latitude.doubleValue(), longitude.doubleValue(), o.getLatitude().doubleValue(), o.getLongitude().doubleValue()));
                return shopVo;
            }).sorted((o1, o2) -> {
                return o1.getDistance().compareTo(o2.getDistance());
            }).filter(c->{
                if(null == type){
                    return true;
                }
                if(Arrays.asList(c.getTypes()).indexOf(type) >= 0){
                    return true;
                }
                return false;
            }).collect(Collectors.toList());

            return ResponseUtil.ok(collect);
        }else{
            List<WxShopVo> collect = shops.stream().map(o->{
                WxShopVo shopVo = new WxShopVo();
                BeanUtils.copyProperties(o, shopVo);
                shopVo.setOpen(validShop(o.getId()));
                LocalTime[] businessHours = shopBusinessHours(o);
                shopVo.setOpenTime(String.valueOf(businessHours[0]));
                shopVo.setCloseTime(String.valueOf(businessHours[1]));
                return shopVo;
            }).filter(c -> {
                if(null == type){
                    return true;
                }
                if (Arrays.asList(c.getTypes()).indexOf(type) >= 0) {
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
            return ResponseUtil.ok(collect);
        }
    }


    /**
     * 获取营业状态
     * @param litemallShop
     * @return
     */
    private boolean getOpenStatus(LitemallShop shop){
        /*if(litemallShop == null || !litemallShop.getStatus().equals(Constants.SHOP_STATUS_OPEN)){
            return false;
        }else{
            String closeTime = litemallShop.getCloseTime();
            String openTime = litemallShop.getOpenTime();
            DateTimeFormatter timeDtf = DateTimeFormatter.ofPattern("HH:mm");
            LocalTime startTimes = LocalTime.parse(openTime, timeDtf);
            LocalTime endTime = LocalTime.parse(closeTime, timeDtf);
            LocalTime now = LocalTime.now();
            Integer dayOfWeek = LocalDateTime.now().getDayOfWeek().getValue();
            //判断星期
            if(litemallShop.getWeeks() == null || !Arrays.asList(litemallShop.getWeeks()).contains(dayOfWeek)){
                return false;
            }
            //判断每天开业时间
            if(now.compareTo(startTimes) != 1 && now.compareTo(endTime) != -1){
                return false;
            }
        }
        return true;*/
        // 假设门店的营业时间已经存在于 shop.getWeeksTime() 集合中
        List<LocalTime[]> weeksTime = shop.getWeeksTime();
        if (weeksTime == null) {
            return false;
        }
        // 获取当前日期和时间
        LocalDate currentDate = LocalDate.now();
        LocalTime currentTime = LocalTime.now();
        if(StrUtil.isNotEmpty(shop.getTimezone())){
            // 设置选择的时区
            ZoneId zoneId = ZoneId.of(shop.getTimezone());
            // 获取当前日期
            currentDate = LocalDate.now(zoneId);
            // 获取当前时间
            currentTime = LocalTime.now(zoneId);
        }
        // 获取当前是星期几
        DayOfWeek currentDayOfWeek = currentDate.getDayOfWeek();

        // 获取对应的门店营业时间
        LocalTime[] businessHours = weeksTime.get(currentDayOfWeek.getValue() - 1);

        // 判断当前时间是否处于门店的开业时间范围内
        boolean isOpen = currentTime.isAfter(businessHours[0]) && currentTime.isBefore(businessHours[1]);
        shop.setStatus(isOpen ? (short) 1 : (short) 2);
        List<AdminShopSpecialDateDTO> specialDateList = shop.getSpecial();
        if(specialDateList!=null){
            LocalDate today = LocalDate.now();
            // 遍历集合中的每个AdminShopSpecialDateDTO对象
            for (AdminShopSpecialDateDTO dto : specialDateList) {
                LocalDate specialDate = dto.getSpecialDate();
                LocalTime[] specialTime = dto.getSpecialTime();

                // 在这里进行特定逻辑处理，判断门店是否营业
                // 判断specialDate是否是今天
                if (!specialDate.isEqual(today)) {
                    continue;
                }
                // 判断当前时间是否在营业时间范围内
                isOpen = currentTime.isAfter(specialTime[0]) && currentTime.isBefore(specialTime[1]);
            }
        }
        return isOpen;
    }

    /**
     * 有效商店
     *
     * @param shopId 商店id
     * @return {@link ResponseUtil.Response}<{@link Object}>
     */
    private Boolean validShop(Integer shopId) {
        if (shopId == null) {
            return false;
        }
        LitemallShop shop = litemallShopService.findById(shopId);
        //判断门店状态
        /*if (litemallShop == null || !litemallShop.getStatus().equals(Constants.SHOP_STATUS_OPEN)) {
            return false;
        } else {
            String closeTime = litemallShop.getCloseTime();
            String openTime = litemallShop.getOpenTime();
            DateTimeFormatter timeDtf = DateTimeFormatter.ofPattern("HH:mm");
            LocalTime startTimes = LocalTime.parse(openTime, timeDtf);
            LocalTime endTime = LocalTime.parse(closeTime, timeDtf);
            LocalTime now = LocalTime.now();
            Integer dayOfWeek = LocalDateTime.now().getDayOfWeek().getValue();
            //判断星期
            if (litemallShop.getWeeks() != null && !Arrays.asList(litemallShop.getWeeks()).contains(dayOfWeek)) {
                return false;
            }
            //判断每天开业时间
            if (!(now.compareTo(startTimes) == 1 && now.compareTo(endTime) == -1)) {
                return false;
            }
        }
        return true;*/
        // 假设门店的营业时间已经存在于 shop.getWeeksTime() 集合中
        List<LocalTime[]> weeksTime = shop.getWeeksTime();
        if (weeksTime == null) {
            return false;
        }
        // 获取当前日期和时间
        LocalDate currentDate = LocalDate.now();
        LocalTime currentTime = LocalTime.now();
        if(StrUtil.isNotEmpty(shop.getTimezone())){
            // 设置选择的时区
            ZoneId zoneId = ZoneId.of(shop.getTimezone());
            // 获取当前日期
            currentDate = LocalDate.now(zoneId);
            // 获取当前时间
            currentTime = LocalTime.now(zoneId);
        }

        // 获取当前是星期几
        DayOfWeek currentDayOfWeek = currentDate.getDayOfWeek();

        // 获取对应的门店营业时间
        LocalTime[] businessHours = weeksTime.get(currentDayOfWeek.getValue() - 1);

        // 判断当前时间是否处于门店的开业时间范围内
        boolean isOpen = currentTime.isAfter(businessHours[0]) && currentTime.isBefore(businessHours[1]);
        List<AdminShopSpecialDateDTO> specialDateList = shop.getSpecial();
        if(specialDateList!=null){
            LocalDate today = LocalDate.now();
            // 遍历集合中的每个AdminShopSpecialDateDTO对象
            for (AdminShopSpecialDateDTO dto : specialDateList) {
                LocalDate specialDate = dto.getSpecialDate();
                LocalTime[] specialTime = dto.getSpecialTime();

                // 在这里进行特定逻辑处理，判断门店是否营业
                // 判断specialDate是否是今天
                if (!specialDate.isEqual(today)) {
                    continue;
                }
                // 判断当前时间是否在营业时间范围内
                isOpen = currentTime.isAfter(specialTime[0]) && currentTime.isBefore(specialTime[1]);
            }
        }
        return isOpen;
    }

    /**
     * 判断当前时间是否与给定店铺的时间相同。
     * 如果店铺的时区为空，则直接返回 true。
     *
     * @param shopId 店铺ID
     * @return 如果当前时间与店铺时间相同，则返回 true；否则返回 false
     */
    public Object regionTimeShop(Integer shopId) {
        if (shopId == null) {
            return false;
        }
        LitemallShop shop = litemallShopService.findById(shopId);
        // 如果时区为 null，直接返回 true
        if (ObjectUtil.isEmpty(shop.getTimezone())) {
            return ResponseUtil.ok(true);
        }
        // 获取当前日期和时间，并将秒数部分截断，使精度变为分钟
        LocalDateTime currentTime = LocalDateTime.now().truncatedTo(java.time.temporal.ChronoUnit.MINUTES);
        // 获取带有指定时区的当前时间
        ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(shop.getTimezone()));
        // 获取当前门店的时间，并将秒数部分截断，使精度变为分钟
        LocalDateTime shopTime = zonedDateTime.toLocalDateTime().truncatedTo(java.time.temporal.ChronoUnit.MINUTES);
        // 判断两个 LocalDateTime 对象是否相同
        return ResponseUtil.ok(currentTime.isEqual(shopTime));
    }

}
